<template>
  <!--<div class="inline-flex">-->
  <div class="w-full">
    <span v-if="props.variant === 'text'">
      {{ dict.getName(props.dict, props.modelValue as string) }}
    </span>

    <template v-else-if="props.variant === 'tag'">
      <template v-if="dict.getName(props.dict, props.modelValue)">
        <el-tag v-if="tagCustom.length" :color="tagCustom[0]" :style="{ color: tagCustom[1] || 'white'}">
          {{ dict.getName(props.dict, props.modelValue as string) }}
        </el-tag>
        <el-tag v-else :type="tagType">
          {{ dict.getName(props.dict, props.modelValue as string) }}
        </el-tag>
      </template>
    </template>

    <el-radio-group v-else-if="props.variant === 'radio'" :model-value="value as string" :disabled="props.disabled" :size="props.size" @change="onChange">
      <el-radio v-for="it in list" :key="it.id" :label="String(it.id)" :disabled="it.disabled">
        {{ it.name }}
      </el-radio>
    </el-radio-group>

    <el-radio-group v-else-if="props.variant === 'btn'" :model-value="value as string" :disabled="props.disabled" :size="props.size" @change="onChange">
      <el-radio-button v-for="it in list" :key="it.id" :label="String(it.id)" :disabled="it.disabled">
        {{ it.name }}
      </el-radio-button>
    </el-radio-group>

    <el-checkbox-group v-else-if="props.variant === 'checkbox'" :model-value="value as string[]" :disabled="props.disabled" :size="props.size" @change="onChange">
      <el-checkbox v-for="it in list" :key="it.id" :label="String(it.id)" :disabled="it.disabled">
        {{ it.name }}
      </el-checkbox>
    </el-checkbox-group>

    <el-select
      v-else
      :model-value="value"
      :size="props.size"
      :placeholder="props.placeholder"
      :disabled="props.disabled"
      :style="{ width }"
      :clearable="props.clearable"
      :filterable="props.filterable"
      :multiple="multiple"
      @change="onChange"
    >
      <el-option v-for="it in list" :key="it.id" :value="String(it.id)" :label="it.name" :disabled="it.disabled" />
    </el-select>
  </div>
</template>

<script setup lang="ts">

type ValueType = number | string | string[] | number[]

/**
 * 字典组件
 *
 * 1. 下拉框单选： <Dict v-model="xx" dict="字典key" />
 * 2. 下拉框多选： <Dict v-model="xx" dict="字典key" multiple /> ｜ <Dict v-model="[]" dict="dict_name" multiple />
 * 3. 下拉框可筛选： <Dict v-model="xx" dict="字典key" filterable />
 * 4. 单选按钮或其它类型变体   <Dict v-model="xx" dict="字典key" variant=“radio” />
 *
 * 需要配合 const dict = useDict()
 */
const props = withDefaults(defineProps<{
  // 数组为多选情况
  modelValue: ValueType | null
  // 样式变体
  variant?: 'select' | 'radio' | 'checkbox' | 'btn' | 'text' | 'tag',
  dict: string,
  disabled?: boolean
  placeholder?: string
  size?: 'small' | 'default' | 'large'
  width?: number | string
  // 是否可清空
  clearable?: boolean
  // 是否多选，variant 类型优先
  multiple?: boolean
  // select 是否可筛选
  filterable?: boolean
}>(), {
  modelValue: null,
  variant: 'select',
  disabled: false,
  clearable: false,
  placeholder: '请选择',
  size: 'default',
  multiple: false,
  filterable: false,
})

const emits = defineEmits<{
  (event: 'change', value: ValueType): void
  (event: 'update:modelValue', value: ValueType): void
}>()

const dict = useDict()

const isMultiple = computed(() => (props.multiple && ['select', 'btn'].includes(props.variant)) || props.variant === 'checkbox')

const value = computed(() => {
  if (props.modelValue === null) {
    return null
  }
  if (isMultiple.value) {
    if (Array.isArray(props.modelValue)) {
      return props.modelValue.map<string>((it: string | number) => String(it))
    }
    return String(props.modelValue).split(',').filter((it) => it)
  }
  return String(props.modelValue)
})

const list = computed(() => dict.get(props.dict))

const width = computed(() => {
  if (!props.width) {
    return '100%'
  }
  if (typeof props.width === 'number') {
    return `${props.width}px`
  }
  return props.width
})

const onChange = (val: string | string[]) => {
  if (isMultiple.value) {
    if (Array.isArray(props.modelValue)) {
      let value: any[] = Array.isArray(val) ? val : (val ? [val] : [])
      if (list.value.length && typeof list.value[0] === 'number') {
        value = value.map((it) => Number(it))
      }
      emits('update:modelValue', value)
      emits('change', value)
    } else {
      const value = Array.isArray(val) ? val.join(',') : val
      emits('update:modelValue', value)
      emits('change', value)
    }
  } else if (typeof props.modelValue === 'number') {
    emits('update:modelValue', Number(val))
    emits('change', Number(val))
  } else {
    const value = Array.isArray(val) ? val.join(',') : val
    emits('update:modelValue', value)
    emits('change', 'value')
  }
}

const tagType = computed<any>(() => {
  const type = dict.getValue(props.dict, props.modelValue)?.color

  return !type || type === 'primary' || type.includes(';') ? '' : type
})

const tagCustom = computed(() => {
  const list = (dict.getValue(props.dict, props.modelValue)?.color || '').split(';').filter((it) => it)
  return list.length === 2 ? list : []
})

</script>

<style scoped lang="scss">

</style>
